package game;

import java.util.ArrayList;
import java.util.List;
import game.screens.GameScreen;
import game.screens.StartupScreen;
import game.screens.WaitingScreen;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;

import session.Session;
import shared.Message;
import shared.io.game.EndGame;
import shared.io.game.GameState;
import shared.io.game.Maze2;
import shared.io.game.Player;
import shared.io.game.Room;


public class Game extends StateBasedGame {

   /**
    * Title
    */
   public static final String TITLE = "Lost in the Dungeon";
   /**
    * List of players in the game
    */
   private List<Player> players;
   /**
    * Maze object. Calculates what rooms can be seen.
    */
   private Maze2 maze;
   /**
    * The client session
    */
   private Session session;
   /**
    * You, the player.
    */
   private Player player;
   /**
    * List of currently visible rooms
    */
   private List<Room> rooms = new ArrayList<Room>();
   /**
    * Queue of incoming messages
    */
   private List<Message> messages;
   /**
    * Has the exit been found?
    */
   private boolean gameOver;
   /**
    * Game state
    */
   private int gameStateIndex = 0;
   
   public Game() {
      super(TITLE);
      
      try {
         players = new ArrayList<Player>();
         messages = new ArrayList<Message>();
      } catch (Exception e) {
         session.close();
      }
      
   }

   @Override
   public void initStatesList(GameContainer arg0) throws SlickException {
      addState(new StartupScreen(this));
      addState(new WaitingScreen(this));
      addState(new GameScreen(this));
   }

   public Session getSession() {
      return session;
   }
   
   public void setRooms(List<Room> rooms) {
      synchronized (this.rooms) {
         this.rooms = rooms;
      }
   }
   /**
    * Sets the current game state
    */
   public void setState(GameState state) {
      setScreen(GameScreen.ID);
      //if (gameOver) return;
      if (gameStateIndex < state.getIndex()) {
         gameStateIndex = state.getIndex();
         setRooms(maze.getVisibleRooms(state.getPlayers(), 5));
         setPlayerLocations(state.getPlayers());
      }
   }
   /**
    * Changes the current sceen. If set to same doesn't change.
    */
   public void setScreen(int id) {
      enterState(id);
   }
   /**
    * Exit has been found.
    */
   public void setEndGame(EndGame endGame) {
      setRooms(maze.getAllRooms());
      gameOver = true;
   }
   /**
    * Adds a player to the game
    */
   public void addPlayer(Player player) {
      if (!players.contains(player)) {
         players.add(player);
      }
   }
   
   public void addPlayers(List<Player> players) {
      for (Player player : players) {
         addPlayer(player);
      }
   }
   
   public List<Player> getPlayers() {
      return players;
   }

   
   public Player getPlayer() {
      return player;
   }
   
   public void setPlayerLocations(List<Player> players) {
      players.remove(player);
      players.add(player);
      this.players = players;
   }

   public List<Room> getRooms() {
      synchronized (this.rooms) {
         return rooms;
      }
   }
   
   public void addMessage(Message message) {
      messages.add(message);
   }
   
   public Message getMessage() {
      if (messages.size() == 0) return null;
      return messages.remove(0);
   }

   public void setPlayer(Player player) {
      this.player = player;
   }

   public Maze2 getMaze() {
      return maze;
   }

   public void setMaze(Maze2 maze) {
      this.maze = maze;
   }

   public void setSession(Session session) {
      this.session = session;
   }
   
}
